using System;
using System.Collections.Generic;
using System.Text;

namespace Noein.GeneticAlgorithm.Final
{
    /// <summary>
    /// Take a list of individuals, and a float array of their fitnesses.
    /// Use some statistics to select some for passing on.
    /// </summary>
    public class Selection : GeneticAlgorithm.Selection<LispLib.Interpreter.Pair, Object, Problem>
    {
        public Selection(
            float crossoverRate, float mutationRate, int offspringSize,
            Crossover<LispLib.Interpreter.Pair, Object> crossover,
            Mutation<LispLib.Interpreter.Pair, Object> mutation)
            : base(crossoverRate, mutationRate, offspringSize, crossover, mutation)
        {


        }

        #region Juan's stuff

        //a delegate represening an individual's fitness
        public delegate float getFitness();

        //the individuals and their fitnesses
        Individual<LispLib.Interpreter.Pair, LispLib.Interpreter.Pair>[] indies;

        /// <summary>
        /// Take a group of individuals, and pick us some survivors.
        /// Return a selection of our individuals.  Our first implementation is the binary round-robin tournament.
        /// Two random individuals are selected, their fitnesses compared, and the winner is kept.
        /// </summary>
        /// <param name="indies"></param>
        /// <param name="fitnesses"></param>
        public Individual<LispLib.Interpreter.Pair, LispLib.Interpreter.Pair>[] getSurvivors(Individual<LispLib.Interpreter.Pair, LispLib.Interpreter.Pair>[] indies, int popSize)
        {

            this.indies = indies;
            Individual<LispLib.Interpreter.Pair, LispLib.Interpreter.Pair>[] survivors = new Individual<LispLib.Interpreter.Pair, LispLib.Interpreter.Pair>[popSize];

            //random numbers:
            Random r = new Random();

            //now populate the list of survivors according to population size, and the method of selection (tournament)
            int first = 0;
            int second = 0;
            for (int i = 0; i < survivors.Length; i++)
            {
                first = r.Next(0, indies.Length);
                while (second == first)
                {
                    second = r.Next(0, indies.Length);
                }//loop

                if (indies[first].getFitness() == indies[second].getFitness())
                {
                    //do not proceed with the loop if there is a tie
                    i--;
                }
                //the more fit one survives
                else if (indies[first].getFitness() > indies[second].getFitness())
                {
                    survivors[i] = indies[first];
                }
                else if (indies[first].getFitness() < indies[second].getFitness())
                {
                    survivors[i] = indies[second];
                }//conditional

                //reset our random ints
                first = 0;
                second = 0;
            }//loop


            return survivors;



        }//getSurvivors

        #endregion

    }//Selection
}//namespace GeneticAlgorithm

